/************************************************************************

								Heroes IV
					  Copyright 2001, The 3DO Company

	------------------------------------------------------------------
  						 abstract_combat_ai_action.h

	$Header: $

	$NoKeywords: $

 ************************************************************************/

#if !defined( ABSTRACT_COMBAT_AI_ACTION_H_INCLUDED )
#define ABSTRACT_COMBAT_AI_ACTION_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <assert.h>
#include <float.h>
#include <limits>
#include "counted_ptr.h"

class t_battlefield;
class t_combat_ai;

// Defines one possible AI action. Details are in subclasses.
class t_abstract_combat_ai_action : public t_counted_object
{
public:

	// Quick constructors. Include values if known
	explicit t_abstract_combat_ai_action( t_battlefield& battlefield,
										  bool never_use = false,
										  double weight = std::numeric_limits<double>::quiet_NaN());

	explicit t_abstract_combat_ai_action( t_battlefield& battlefield, double weight);

	// Set / Get functions
	double get_basic_weight( t_combat_ai const& owner );
	bool   get_never_use( t_combat_ai const& owner );
	double get_weight( t_combat_ai const& owner );
	bool   has_been_weighed(void) const;

	// Do this action on the battlefield
	virtual void perform_action(void) = 0;

protected:
	// Get the weight of this action
	// Pass in the t_combat_ai that owns this action object
	void			set_weight( double weight );
	virtual void	weigh_action(t_combat_ai const& owner) = 0;

	t_battlefield&	m_battlefield;
	// Data needed to process all action types
	// Mark this action as "do not perform", regardless of weight
	bool			m_never_use;

	// Weight of this action
	double			m_basic_weight;
	double			m_random_weight;
};


inline
t_abstract_combat_ai_action::t_abstract_combat_ai_action( t_battlefield& battlefield,
														  bool never_use, double weight)
	: m_never_use(never_use), m_battlefield( battlefield )
{
	set_weight( weight );
	assert(std::numeric_limits<double>::has_quiet_NaN); // Defaults are valid, right?
}


inline
t_abstract_combat_ai_action::t_abstract_combat_ai_action( t_battlefield& battlefield,
														  double weight)
	: m_never_use(false), m_battlefield( battlefield )
{
	set_weight( weight );
	assert(std::numeric_limits<double>::has_quiet_NaN); // Defaults are valid, right?
}

inline
bool t_abstract_combat_ai_action::get_never_use( t_combat_ai const& owner ) 
{
	if (!has_been_weighed())
		weigh_action( owner );
	return m_never_use;
}

inline double t_abstract_combat_ai_action::get_basic_weight( t_combat_ai const& owner ) 
{
	if (!has_been_weighed())
		weigh_action( owner );
	return m_basic_weight;
}

inline
double t_abstract_combat_ai_action::get_weight( t_combat_ai const& owner )
{
	if (!has_been_weighed())
		weigh_action( owner );
	return m_basic_weight + m_random_weight;
}

inline
bool t_abstract_combat_ai_action::has_been_weighed(void) const
{
	return !_isnan(m_basic_weight);
}


#endif  // COMBAT_AI_ACTION_BASE_H_INCLUDED
